#include "script/ScriptDocumentOperation.h"

using namespace simodo;

/// \file
/// \see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover


variable::Value makeHoverContentsResponse(const std::u16string & kind, const std::u16string & value) {
    return variable::Object {{
        { u"kind", kind },
        { u"value", inout::encodeSpecialChars(value) },
}};
}

variable::Value makeHoverResponse(const std::u16string & hover_text, const lsp::Range & range) {
    return variable::Object {{
        { u"contents", makeHoverContentsResponse(u"plaintext", hover_text) },
        { u"range", lsp::DocumentContext::makeRange(range) },
}};
}


std::u16string ScriptDocumentOperation::makeHoverText(const variable::Variable & var)
{
    std::u16string text = getVariableString(var);

    if (!var.spec().object()->variables().empty())
        text += u"\n#" + variable::toString(var.spec().object());

    return text;
}

variable::Value ScriptDocumentOperation::produceHoverResponse(const lsp::Position & pos) const
{
    for (const variable::Variable & var : _semantic_data.declared())
        if (isOnToken(var.location(), pos))
            return makeHoverResponse(makeHoverText(var), var.location().range());

    for (const auto & [var, loc] : _semantic_data.used())
        if (isOnToken(loc, pos)) {
            std::u16string text = makeHoverText(var);

            if (isRemoteFunctionLaunch(loc))
                text += u"\nRemote launching!";

            return makeHoverResponse(text, loc.range());
        }

    for (const auto & [token, ref] : _semantic_data.refs())
        if (isOnToken(token.location(), pos))
            return makeHoverResponse(ref, token.location().range());

    return { };
}

